<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>网格交易计算器（响应式 V8）</title>
    <style>
        /* --- CSS 样式 (与V7相同) --- */
        :root {
            --primary-color: #007bff;
            --danger-color: #f44336;
            --success-color: #4caf50;
            --warning-color: #ff9800;
            --export-color: #2196f3;
            --import-color: #3f51b5;
            --paste-color: #9c27b0;
            --light-bg: #f7f9fb;
            --header-bg: #ffe2c0;
            --row-bg-even: #f8fcff;
            --border-color: #ddd;
        }
        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Microsoft YaHei", sans-serif;
            background: var(--light-bg);
            margin: 0;
            padding: 15px;
        }
        .container {
            max-width: 1200px;
            margin: 0 auto;
            background: white;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.05);
        }
        h2 { text-align: center; margin-top: 0; margin-bottom: 20px; color: #333; }
        .btn-row {
            display: flex;
            flex-wrap: wrap;
            justify-content: flex-end;
            gap: 8px;
            margin-bottom: 15px;
        }
        button {
            padding: 8px 12px;
            margin: 0;
            border: none;
            border-radius: 6px;
            cursor: pointer;
            font-weight: 500;
            transition: opacity 0.2s;
        }
        button:hover { opacity: 0.85; }
        .add-btn { background: var(--success-color); color: white; }
        .export-btn { background: var(--export-color); color: white; }
        .import-btn { background: var(--import-color); color: white; }
        .copy-btn { background: var(--warning-color); color: white; }
        .paste-btn { background: var(--paste-color); color: white; }
        .delete-btn { background: var(--danger-color); color: white; }
        table { width: 100%; border-collapse: collapse; background: white; }
        th, td { border: 1px solid var(--border-color); padding: 10px 12px; text-align: center; vertical-align: middle; }
        th { background: var(--header-bg); font-weight: 600; white-space: nowrap; }
        tr:nth-child(even) td { background: var(--row-bg-even); }
        input {
            width: 100%;
            min-width: 70px;
            padding: 6px 8px;
            text-align: center;
            border: 1px solid #ccc;
            border-radius: 4px;
            box-sizing: border-box;
        }
        .buyQty, .buyAmt, .maxAmt {
            font-weight: bold;
            color: var(--primary-color);
            font-size: 1.05em;
            display: inline-block;
            padding: 6px 8px;
            box-sizing: border-box;
        }

        /* --- 响应式 (V7) --- */
        @media (max-width: 768px) {
            body { padding: 5px; }
            .container { padding: 10px; box-shadow: none; }
            .btn-row { justify-content: space-between; }
            .btn-row button {
                flex-basis: calc(50% - 4px);
                flex-grow: 1;
                font-size: 14px;
                padding: 10px;
            }
            .btn-row button:last-child:nth-child(odd) { flex-basis: 100%; }
            thead { display: none; }
            tr {
                display: block;
                border: 1px solid var(--border-color);
                border-radius: 8px;
                margin-bottom: 15px;
                background: white !important;
                box-shadow: 0 2px 4px rgba(0,0,0,0.05);
            }
            tr:nth-child(even) td { background: none; }
            td {
                display: flex;
                justify-content: flex-end;
                align-items: center;
                padding: 10px 10px 10px 50%;
                position: relative;
                border: none;
                border-bottom: 1px dotted var(--border-color);
                min-height: 44px;
            }
            td::before {
                content: attr(data-label);
                position: absolute;
                left: 10px;
                top: 50%;
                transform: translateY(-50%);
                font-weight: 600;
                text-align: left;
                color: #555;
            }
            td:first-child { border-top-left-radius: 8px; border-top-right-radius: 8px; }
            td:last-child { border-bottom: none; border-bottom-left-radius: 8px; border-bottom-right-radius: 8px; }
            input { width: 100%; max-width: 160px; text-align: right; padding: 8px; }
            .buyQty, .buyAmt, .maxAmt { width: auto; text-align: right; padding: 8px 0; }
            td[data-label="操作"]::before { display: none; }
            td[data-label="操作"] { padding: 10px; }
            .delete-btn { width: 100%; padding: 10px; font-size: 16px; }
        }
    </style>
</head>
<body>

<div class="container">
    <h2>网格交易计算器（响应式 V8）</h2>

    <div class="btn-row">
        <button class="add-btn" id="addBtn">＋ 新增一行</button>
        <button class="export-btn" id="exportBtn">导出配置</button>
        <button class="import-btn" id="importBtn">导入配置</button>
        <button class="copy-btn" id="copyBtn">复制配置</button>
        <button class="paste-btn" id="pasteBtn">粘贴配置</button>
    </div>

    <table id="tradeTable">
        <thead>
        <tr>
            <th>股票名称</th>
            <th>步长</th>
            <th>每笔股数</th>
            <th>基准价格</th>
            <th>网格下限</th>
            <th>上次交易价</th>
            <th>当前价格</th>
            <th>应买入股数</th>
            <th>应买入金额</th>
            <th>最大仓位金额</th>
            <th>操作</th>
        </tr>
        </thead>
        <tbody id="tableBody"></tbody>
    </table>
</div>

<script>
    // ✅ V8: 将所有代码包裹在 DOMContentLoaded 事件中
    document.addEventListener("DOMContentLoaded", function() {

        const STORAGE_KEY = "grid_trade_config_v8";
        const tableBody = document.getElementById("tableBody");

        // ✅ V8: 绑定顶部按钮的事件监听器
        document.getElementById("addBtn").addEventListener("click", () => addRow());
        document.getElementById("exportBtn").addEventListener("click", exportConfig);
        document.getElementById("importBtn").addEventListener("click", importConfig);
        document.getElementById("copyBtn").addEventListener("click", copyConfig);
        document.getElementById("pasteBtn").addEventListener("click", pasteConfig);

        // ✅ V8: 使用事件委托处理表格内部的点击和输入
        tableBody.addEventListener("click", function(e) {
            // 监听 "删除" 按钮
            if (e.target.classList.contains("delete-btn")) {
                deleteRow(e.target);
            }
        });

        tableBody.addEventListener("input", function(e) {
            // 监听需要重新计算的输入框
            if (e.target.classList.contains("recalc-trigger")) {
                recalcRow(e.target);
            }
        });

        tableBody.addEventListener("change", function(e) {
            // 监听所有配置输入框的 "change" 事件（失去焦点时）
            if (e.target.classList.contains("config-input")) {
                saveConfig();
            }
        });


        // --- 函数定义 ---
        // (现在它们都在 DOMContentLoaded 的作用域内，互相可见)

        function addRow(data = {}) {
            const tr = document.createElement("tr");

            // ✅ V8: 移除所有 on... 属性，改用 class 标记
            tr.innerHTML = `
            <td data-label="股票名称"><input class="config-input" name="name" value="${data.name || ''}"></td>
            <td data-label="步长"><input class="config-input recalc-trigger" name="step" type="number" step="0.001" value="${data.step || 0.001}"></td>
            <td data-label="每笔股数"><input class="config-input recalc-trigger" name="qty" type="number" step="100" value="${data.qty || 100}"></td>
            <td data-label="基准价格"><input class="config-input recalc-trigger" name="base" type="number" step="0.001" value="${data.base || 1.000}"></td>
            <td data-label="网格下限"><input class="config-input recalc-trigger" name="lower" type="number" step="0.001" value="${data.lower || 0.800}"></td>
            <td data-label="上次交易价"><input class="config-input recalc-trigger" name="last" type="number" step="0.001" value="${data.last || 1.000}"></td>
            <td data-label="当前价格"><input class="config-input recalc-trigger" name="current" type="number" step="0.001" value="${data.current || ''}"></td>
            <td data-label="应买入股数"><span class="buyQty">0</span></td>
            <td data-label="应买入金额"><span class="buyAmt">0</span></td>
            <td data-label="最大仓位金额"><span class="maxAmt">0</span></td>
            <td data-label="操作"><button class="delete-btn">删除</button></td>
            `;

            tableBody.appendChild(tr);
            // 触发一次计算 (找到行内的任一 recalc-trigger 输入框)
            recalcRow(tr.querySelector(".recalc-trigger"));
        }

        function recalcRow(el) {
            if (!el) return;
            const tr = el.closest("tr");
            if (!tr) return;

            // V8: 通过 name 属性查找输入框，更稳健
            const getValue = (name) => parseFloat(tr.querySelector(`input[name="${name}"]`)?.value) || 0;

            const step = getValue("step");
            const qty = getValue("qty");
            const base = getValue("base");
            const lower = getValue("lower");
            const last = getValue("last");
            const current = getValue("current");

            const gridCount = step > 0 ? Math.ceil((base - lower) / step) : 0;
            const gridDiff = (step > 0 && last > current) ? (last - current) / step : 0;
            const buyQty = gridDiff > 0 ? Math.ceil(gridDiff) * qty : 0;

            const buyAmt = (buyQty * current).toFixed(3);
            const totalQty = qty * gridCount;
            const maxAmt = (totalQty * lower).toFixed(3);

            tr.querySelector(".buyQty").textContent = buyQty;
            tr.querySelector(".buyAmt").textContent = buyAmt;
            tr.querySelector(".maxAmt").textContent = maxAmt;

            // V8: 计算后立即保存
            saveConfig();
        }

        function deleteRow(btn) {
            btn.closest("tr").remove();
            saveConfig();
        }

        function saveConfig() {
            const rows = document.querySelectorAll("#tableBody tr");
            const list = [];
            rows.forEach(tr => {
                const inputs = tr.querySelectorAll("input");
                if (inputs.length < 7) return; // 确保行是完整的

                const data = {};
                inputs.forEach(input => {
                    data[input.name] = input.type === 'number' ? (parseFloat(input.value) || 0) : input.value;
                });
                list.push(data);
            });
            localStorage.setItem(STORAGE_KEY, JSON.stringify(list));
        }

        function exportConfig() {
            const data = localStorage.getItem(STORAGE_KEY) || "[]";
            const blob = new Blob([data], { type: "application/json" });
            const a = document.createElement("a");
            a.href = URL.createObjectURL(blob);
            a.download = "grid_trade_config_v8.json";
            a.click();
        }

        function importConfig() {
            const input = document.createElement("input");
            input.type = "file";
            input.accept = "application/json";
            input.onchange = e => {
                const file = e.target.files[0];
                if (!file) return;
                const reader = new FileReader();
                reader.onload = e2 => {
                    try {
                        const data = JSON.parse(e2.target.result);
                        tableBody.innerHTML = ""; // 清空表格
                        data.forEach(addRow); // addRow 内部会计算
                        saveConfig(); // 确保最终保存
                    } catch (err) {
                        alert("导入失败：文件不是有效的 JSON 配置。");
                    }
                };
                reader.readAsText(file);
            };
            input.click();
        }

        function copyConfig() {
            const data = localStorage.getItem(STORAGE_KEY) || "[]";
            if (navigator.clipboard) {
                navigator.clipboard.writeText(data).then(() => {
                    alert("配置已复制到剪贴板！");
                }).catch(err => {
                    alert("复制失败: " + err);
                });
            } else {
                alert("浏览器不支持剪贴板 API，复制失败。");
            }
        }

        async function pasteConfig() {
            if (!navigator.clipboard) {
                alert("浏览器不支持剪贴板 API，粘贴失败。");
                return;
            }
            try {
                const text = await navigator.clipboard.readText();
                const data = JSON.parse(text);

                tableBody.innerHTML = "";
                data.forEach(addRow);
                saveConfig();
                alert("配置已从剪贴板粘贴并导入！");

            } catch (err) {
                alert("粘贴失败：剪贴板内容不是有效的 JSON 配置。\n" + err);
            }
        }

        // --- 初始加载 ---
        const saved = localStorage.getItem(STORAGE_KEY);
        if (saved) {
            JSON.parse(saved).forEach(addRow);
        }

    }); // 结束 DOMContentLoaded
</script>
</body>
</html>